<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Editor</title>
  <link rel="stylesheet" href="libs/bootstrap/5.1.1/bootstrap.min.css">
  <link rel="stylesheet" href="libs/normalize/8.0.1/normalize.min.css">

  <!--markdown preview-->
  <link rel="stylesheet" href="libs/markdown-it/plugins/highlightjs/atom-one-light.css">
  <link rel="stylesheet" href="libs/markdown-it/style/markdown.css">
  <style>
    html, body, .full-height {
      height: 100%;
    }

    body {
      overflow-x: hidden;
      padding-bottom: 160px;
      background-color: #fbfbfb;
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      font-size: 14px;
      line-height: 1.42857143;
      color: #333;
    }



    .editor-header {
      border-bottom: 1px solid #e8e8e8;
      position: relative;
      display: flex;
      justify-content: space-between;
      align-items: center;
      width: 100%;
    }

    .title {
      line-height: 1rem;
      font-size: .8rem;
      margin-bottom: .77999rem;
      padding-top: .22001rem;
      font-weight: 500;
      color: #a0aabf;
      letter-spacing: 1px;
      text-transform: uppercase;
      padding-left: 16px;
      padding-right: 16px;
      margin-top: 1rem;
    }

    .source {
      width: 100%;
      font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
      font-size: 13px;
      padding: 2px;
    }

    .result-html {
      padding: 2px 10px;
      overflow: auto;
      background-color: #fff;
      border: 1px solid #ccc;
      border-radius: 4px;
    }

    textarea {
      font-family: inherit;
      font-size: inherit;
      line-height: inherit;
    }

  </style>
</head>
<body>
  <div class="container full-height">
    <div class="row full-height">
      <section class="col-6 full-height">
        <div class="editor-header">
          <h3 class="title">Markdown</h3>
          <div class="btn-group" role="group" aria-label="Basic example">
            <button type="button" class="btn btn-outline-secondary source-clear">Clear</button>
          </div>
        </div>
        <textarea class="source full-height"></textarea>
      </section>
      <section class="col-6 full-height">
        <div class="editor-header">
          <h3 class="title">Preview</h3>
          <!--<div class="btn-group" role="group" aria-label="Basic outlined example">
            <button type="button" class="btn btn-outline-secondary" data-result-as="html">Html</button>
          </div>-->
        </div>
        <div class="result-html full-height"></div>
      </section>
    </div>

  </div>
<script src="libs/jquery/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script src="libs/bootstrap/5.1.1/bootstrap.min.js"></script>
<script src="libs/markdown-it/markdown-it.min.js"></script>
<script src="libs/markdown-it/plugins/highlightjs/highlight.min.js"></script>
<script src="libs/markdown-it/plugins/markdown-it-container/dist/markdown-it-container.min.js"></script>
<script src="libs/markdown-it/plugins/markdown-it-anchor/dist/markdownItAnchor.umd.js"></script>
<script src="libs/markdown-it/plugins/markdown-it-toc-done-right/markdownItTocDoneRight.umd.js"></script>
<script src="libs/markdown-it/plugins/markdown-it-emoji/dist/markdown-it-emoji.js"></script>
<script src="libs/markdown-it/plugins/markdown-it-task-checkbox/markdown-it-task-checkbox.js"></script>
<script src="libs/markdown-it/plugins/markdown-it-mathjax/markdown-it-mathjax.js"></script>
<script src="libs/markdown-it/plugins/markdownlint/markdownlint-browser.min.js"></script>
<script src="libs/markdown-it/plugins/markdownlint/markdownlint-rule-helpers-browser.min.js"></script>
<script src="libs/markdown-it/rules/rules.js"></script>
<script src="libs/markdown-it/plugins/plugins.js"></script>
<script>


$(function () {
  $(".source").val(mdStr)
  var _view = 'html';
  var md = function () {
    let md = window.markdownit({
      breaks: true,
      html: true,
      linkify: true,
      typographer:  true,
      highlight: function(str, lang) {
        if (!(lang && hljs.getLanguage(lang))) {
          return '';
        }

        return hljs.highlight(lang, str, true).value;
      },
      // 新增自定义配置
      lint: true,       // 是否对markdown文件进行lint,
      wrapper: 'div',
      wrapperClass: 'markdown__view',
      assetsPublicPath: function (src) {
        const relativeToAbsolutePath = function relativeToAbsolutePath(base, relative) {
          const stack = base.split("/"), parts = relative.split("/");
          for (let i = 0; i < parts.length; i++) {
            if (parts[i] === ".")
              continue;
            if (parts[i] === "..")
              stack.pop();
            else
              stack.push(parts[i]);
          }
          return stack.join("/");
        };

        const regxPath = /^https?:\/\//i;
        if (!regxPath.test(src)) {
          return relativeToAbsolutePath(`${location.protocol}//${location.host}/markdown-preview/docs/hsq/`, src);
        }
        return src;
      },
    });
    markdownItRules.overWriteAllRules(md);
    markdownItPlugins.loadPlugins(md);
    return md;
  }();
  var scrollMap;
  $(window).on("resize", (function() {
    scrollMap = null;
  }));

  function buildScrollMap() {
    var i, offset, nonEmptyList, pos, a, b, lineHeightMap, linesCount, acc, sourceLikeDiv, textarea = $(".source"), _scrollMap;
    sourceLikeDiv = $("<div />").css({
      position: "absolute",
      visibility: "hidden",
      height: "auto",
      width: textarea[0].clientWidth,
      "font-size": textarea.css("font-size"),
      "font-family": textarea.css("font-family"),
      "line-height": textarea.css("line-height"),
      "white-space": textarea.css("white-space")
    }).appendTo("body");
    offset = $(".result-html").scrollTop() - $(".result-html").offset().top;
    _scrollMap = [];
    nonEmptyList = [];
    lineHeightMap = [];
    acc = 0;
    textarea.val().split("\n").forEach((function(str) {
      var h, lh;
      lineHeightMap.push(acc);
      if (str.length === 0) {
        acc++;
        return;
      }
      sourceLikeDiv.text(str);
      h = parseFloat(sourceLikeDiv.css("height"));
      lh = parseFloat(sourceLikeDiv.css("line-height"));
      acc += Math.round(h / lh);
    }));
    sourceLikeDiv.remove();
    lineHeightMap.push(acc);
    linesCount = acc;
    for (i = 0; i < linesCount; i++) {
      _scrollMap.push(-1);
    }
    nonEmptyList.push(0);
    _scrollMap[0] = 0;
    $(".line").each((function(n, el) {
      var $el = $(el), t = $el.data("line");
      if (t === "") {
        return;
      }
      t = lineHeightMap[t];
      if (t !== 0) {
        nonEmptyList.push(t);
      }
      _scrollMap[t] = Math.round($el.offset().top + offset);
    }));
    nonEmptyList.push(linesCount);
    _scrollMap[linesCount] = $(".result-html")[0].scrollHeight;
    pos = 0;
    for (i = 1; i < linesCount; i++) {
      if (_scrollMap[i] !== -1) {
        pos++;
        continue;
      }
      a = nonEmptyList[pos];
      b = nonEmptyList[pos + 1];
      _scrollMap[i] = Math.round((_scrollMap[b] * (i - a) + _scrollMap[a] * (b - i)) / (b - a));
    }
    return _scrollMap;
  }

  var syncResultScroll = _.debounce((function() {
    var textarea = $(".source"), lineHeight = parseFloat(textarea.css("line-height")), lineNo, posTo;
    lineNo = Math.floor(textarea.scrollTop() / lineHeight);
    if (!scrollMap) {
      scrollMap = buildScrollMap();
    }
    posTo = scrollMap[lineNo];
    $(".result-html").stop(true).animate({
      scrollTop: posTo
    }, 100, "linear");
  }), 50, {
    maxWait: 50
  });
  // Synchronize scroll position from result to source
  var syncSrcScroll = _.debounce((function() {
    var resultHtml = $(".result-html"), scrollTop = resultHtml.scrollTop(), textarea = $(".source"), lineHeight = parseFloat(textarea.css("line-height")), lines, i, line;
    if (!scrollMap) {
      scrollMap = buildScrollMap();
    }
    lines = Object.keys(scrollMap);
    if (lines.length < 1) {
      return;
    }
    line = lines[0];
    for (i = 1; i < lines.length; i++) {
      if (scrollMap[lines[i]] < scrollTop) {
        line = lines[i];
        continue;
      }
      break;
    }
    textarea.stop(true).animate({
      scrollTop: lineHeight * line
    }, 100, "linear");
  }), 50, {
    maxWait: 50
  });

  // Setup listeners
  $(".source").on("keyup paste cut mouseup", _.debounce(updateResult, 300, {
    maxWait: 500
  }));
  $(".source").on("touchstart mouseover", (function() {
    $(".result-html").off("scroll");
    $(".source").on("scroll", syncResultScroll);
  }));
  $(".result-html").on("touchstart mouseover", (function() {
    $(".source").off("scroll");
    $(".result-html").on("scroll", syncSrcScroll);
  }));
  $(".source-clear").on("click", (function(event) {
    $(".source").val("");
    updateResult();
    event.preventDefault();
  }));

  function updateResult() {
    var source = $(".source").val();
    var resultEl = $('.result-html');
    var resultSrcEl = $(".result-src");
    resultEl.show();
    resultSrcEl.hide();
    resultEl.html(md.render(source));
  }

  updateResult();
})

var mdStr = `---
  __Advertisement :)__

  - __[pica](https://nodeca.github.io/pica/demo/)__ - high quality and fast image
    resize in browser.
  - __[babelfish](https://github.com/nodeca/babelfish/)__ - developer friendly
    i18n with plurals support and easy syntax.

  You will like those projects!

  ---

  # h1 Heading 8-)
  ## h2 Heading
  ### h3 Heading
  #### h4 Heading
  ##### h5 Heading
  ###### h6 Heading


  ## Horizontal Rules

  ___

  ---

  ***


  ## Typographic replacements

  Enable typographer option to see result.

  (c) (C) (r) (R) (tm) (TM) (p) (P) +-

  test.. test... test..... test?..... test!....

  !!!!!! ???? ,,  -- ---

  "Smartypants, double quotes" and 'single quotes'


  ## Emphasis

  **This is bold text**

  __This is bold text__

  *This is italic text*

  _This is italic text_

  ~~Strikethrough~~


  ## Blockquotes


  > Blockquotes can also be nested...
  >> ...by using additional greater-than signs right next to each other...
  > > > ...or with spaces between arrows.


  ## Lists

  Unordered

  + Create a list by starting a line with \\\`+\\\`, \\\`-\\\`, or \\\`*\\\`
  + Sub-lists are made by indenting 2 spaces:
    - Marker character change forces new list start:
      * Ac tristique libero volutpat at
      + Facilisis in pretium nisl aliquet
      - Nulla volutpat aliquam velit
  + Very easy!

  Ordered

  1. Lorem ipsum dolor sit amet
  2. Consectetur adipiscing elit
  3. Integer molestie lorem at massa


  1. You can use sequential numbers...
  1. ...or keep all the numbers as \\\`1.\\\`

  Start numbering with offset:

  57. foo
  1. bar


  ## Code

  Inline \\\`code\\\`

  Indented code

      // Some comments
      line 1 of code
      line 2 of code
      line 3 of code


  Block code "fences"

  \\\`\\\`\\\`
  Sample text here...
  \\\`\\\`\\\`

  Syntax highlighting

  \\\`\\\`\\\` js
  var foo = function (bar) {
    return bar++;
  };

  console.log(foo(5));
  \\\`\\\`\\\`

  ## Tables

  | Option | Description |
  | ------ | ----------- |
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |

  Right aligned columns

  | Option | Description |
  | ------:| -----------:|
  | data   | path to data files to supply the data that will be passed into templates. |
  | engine | engine to be used for processing templates. Handlebars is the default. |
  | ext    | extension to be used for dest files. |


  ## Links

  [link text](http://dev.nodeca.com)

  [link with title](http://nodeca.github.io/pica/demo/ "title text!")

  Autoconverted link https://github.com/nodeca/pica (enable linkify to see)


  ## Images

  ![Minion](https://octodex.github.com/images/minion.png)
  ![Stormtroopocat](https://octodex.github.com/images/stormtroopocat.jpg "The Stormtroopocat")

  Like links, Images also have a footnote style syntax

  ![Alt text][id]

  With a reference later in the document defining the URL location:

  [id]: https://octodex.github.com/images/dojocat.jpg  "The Dojocat"


  ## Plugins

  The killer feature of \\\`markdown-it\\\` is very effective support of
  [syntax plugins](https://www.npmjs.org/browse/keyword/markdown-it-plugin).


  ### [Emojies](https://github.com/markdown-it/markdown-it-emoji)

  > Classic markup: :wink: :crush: :cry: :tear: :laughing: :yum:
  >
  > Shortcuts (emoticons): :-) :-( 8-) ;)

  see [how to change output](https://github.com/markdown-it/markdown-it-emoji#change-output) with twemoji.


  ### [Subscript](https://github.com/markdown-it/markdown-it-sub) / [Superscript](https://github.com/markdown-it/markdown-it-sup)

  - 19^th^
  - H~2~O


  ### [\\\\<ins>](https://github.com/markdown-it/markdown-it-ins)

  ++Inserted text++


  ### [\\\\<mark>](https://github.com/markdown-it/markdown-it-mark)

  ==Marked text==


  ### [Footnotes](https://github.com/markdown-it/markdown-it-footnote)

  Footnote 1 link[^first].

  Footnote 2 link[^second].

  Inline footnote^[Text of inline footnote] definition.

  Duplicated footnote reference[^second].

  [^first]: Footnote **can have markup**

      and multiple paragraphs.

  [^second]: Footnote text.


  ### [Definition lists](https://github.com/markdown-it/markdown-it-deflist)

  Term 1

  :   Definition 1
  with lazy continuation.

  Term 2 with *inline markup*

  :   Definition 2

          { some code, part of Definition 2 }

      Third paragraph of definition 2.

  _Compact style:_

  Term 1
    ~ Definition 1

  Term 2
    ~ Definition 2a
    ~ Definition 2b


  ### [Abbreviations](https://github.com/markdown-it/markdown-it-abbr)

  This is HTML abbreviation example.

  It converts "HTML", but keep intact partial entries like "xxxHTMLyyy" and so on.

  *[HTML]: Hyper Text Markup Language

  ### [Custom containers](https://github.com/markdown-it/markdown-it-container)

  ::: warning
  *here be dragons*
  :::`
</script>
</body>
</html>
